package com.weai.service.impl;

import com.weai.config.DeepSeekConfig;
import com.weai.dto.DepositAIChatRequest;
import com.weai.dto.DepositAIChatResponse;
import com.weai.entity.Task;
import com.weai.repository.TaskRepository;
import com.weai.service.AIModelService;
import com.weai.service.DepositAIService;
import com.weai.util.DateUtils;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * AI助手服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DepositAIServiceImpl implements DepositAIService {

    /**
     * DeepSeek聊天模型
     */
    private final ChatLanguageModel chatModel;
    
    /**
     * DeepSeek配置
     */
    private final DeepSeekConfig deepSeekConfig;
    
    /**
     * AI模型服务
     */
    private final AIModelService aiModelService;

    private final TaskRepository taskRepository;
    
    /**
     * 会话内存缓存，键为会话ID，值为聊天记忆对象
     */
    private final Map<String, ChatMemory> chatMemories = new ConcurrentHashMap<>();
    
    /**
     * AI助手的系统提示信息
     */

    private static final String SYSTEM_PROMPT = """
            **角色定位**：
            你是存款AI服务助手，专注于为内部提供全方位的AI技术支持和服务。你整合了六大核心功能模块，致力于为用户提供专业、精准、高效的AI解决方案。

            **核心功能**：
            1. **AI需求全周期管理** - 支持AI任务的创建、跟踪、协调和闭环管理
            2. **AI周报生成** - 支持AI分析项目进展，并通过AI生成周报
            3. **历史周报月报** - 支持查看历史周报月报
            4. **行内AI解决方案中心** - 提供经内部验证的标准AI实施方案和最佳实践
            5. **智能问答知识库** - 解答技术难题，分享行内AI专家经验（含FAQ论坛）
            6. **全行AI项目仪表盘** - 实时展示各分支机构AI项目进展和成效
            7. **AI研究智库** - 精选最新学术论文、技术报告和行业白皮书
            8. **行业解决方案仓库** - 收录金融同业可借鉴的AI应用案例

            **行为规范**：
            - 使用简短且专业的语言回答用户问题
            - 所有回答使用中文，保持专业性和准确性
            - 当涉及到任务创建时，提取用户需求的核心内容
            
            **功能状态**：
            - 目前系统仅支持通过大模型进行任务/需求的创建功能，其他功能将陆续上线。
            
            **非创建任务场景处理**：
            如识别到用户意图不是创建任务/需求相关，请用幽默且简洁的文字回复用户：
            - 不要编造数据
            - 不要编造尚未实现的功能
            - 只回复文字，不使用表情
            """;

    private static final String SYSTEM_PROMPT_WECHAT = """
            现在是闲聊模式，用户会询问一些系统的功能和操作方法，请根据用户问题进行回答。
            要求：
            - 用中文回复
            - 回答简洁明了，控制在100字以内
            - 用户询问的问题和核心功能无关，请用幽默且简洁的文字回复用户
            - 一定不要编造数据回答用户，不要编造其他暂时没实现的功能
            - 只回复文字，不要回复表情
            - 用户问到系统未开发的相关功能时，请最后加上：可前往  http://10.107.102.153:8080  体验完整在线版功能 ~~~
            - 直接返回结果，不要包含任何其他文字或解释
            """;

    private static final String GET_PROBLEM_TYEP_PROMPT = """ 
            你是存款AI服务助手，负责分析用户输入并判断其是否有想让你帮忙创建、添加、新增任务的意图。请分析用户输入并返回对应的类型代码：
            - 1: 表示用户想要创建新的任务或需求
            - 2: 表示用户想要进行普通对话

            判断规则：
            - 如果用户明确表达了"创建任务"、"添加需求"、"新建任务"、"记录任务"等创建意图的关键词，返回1
            - 如果用户的语句包含工作内容描述，并暗示需要记录或创建任务，返回1
            - 如果用户只是询问系统功能、闲聊或其他非任务创建相关内容，返回2
            
            要求：
            - 仅返回数字1或2
            - 不要包含任何其他文字或解释
            - 基于用户输入的关键词和上下文进行判断

            示例：
            输入:帮我创建一个新任务
            输出:1

            输入:需要记录一下下周培训事项
            输出:1

            输入:今天天气怎么样
            输出:2
            
            输入:系统有什么功能
            输出:2
            """;
    private static final String GEN_PARAMS_PROMPT = """
            你是一个专业的语义分析专家，擅长从用户输入中提取核心任务信息。请遵循以下规则：

            1. 去除所有请求性前缀（如"帮我"、"请"、"需要"等）
            2. 去除所有任务相关后缀（如"提一下任务"、"建立需求"等）
            3. 保留原始任务描述的核心内容
            4. 将任务内容简洁化，但保留关键信息
            5. 如任务描述过长，提取30字以内的核心内容作为标题
            6. 直接返回提取结果，无需任何解释

            示例：
            用户输入：帮我建立一个需求，需求内容是：chaiBI调研
            提取结果：chaiBI调研

            用户输入：RPT录视频并上传，后续指导业务操作;给我提一下任务
            提取结果：RPT录视频并上传，后续指导业务操作

            用户输入：备忘一下，测试需求完成poc，这个任务需要在本周内完成，要测试系统的稳定性和性能表现
            提取结果：测试需求完成poc
            
            用户输入：我需要跟进一下数据治理项目进展情况，需要和各部门负责人沟通协调，收集反馈，然后形成周报
            提取结果：数据治理项目进展跟进及周报
            """;



    // * 获取或创建聊天记忆
    // *
    // * @param conversationId 会话ID
    // * @return 聊天记忆对象
    // */
    //private ChatMemory getChatMemory(String conversationId) {
    @Override
    public DepositAIChatResponse chat(DepositAIChatRequest request, String username) {
        try {

            //通过提示词判断用户的问题类型
            String userMessage = request.getMessage();
            String prompt = GET_PROBLEM_TYEP_PROMPT + "\n\n" + "输入:" + userMessage + "\n" + "输出:";
            String response = aiModelService.chat(prompt);
            
            int problemType = Integer.parseInt(response);
            if (problemType == 1) {
                log.info("用户的问题类型：需求相关");
                // 提取出的关键信息
                String genParams = GEN_PARAMS_PROMPT + "\n\n" + "用户输入：" + userMessage + "\n" + "提取结果：";
                String genParamsResponse = aiModelService.chat(genParams);
                log.info("提取出的需求关键信息：{}", genParamsResponse);
                Task task = new Task();

                // 设置当前周的周一和周日日期
                Map<String, LocalDate> dateRange = DateUtils.getCurrentAndLastWeekDateRange();
                LocalDate startOfWeek = dateRange.get("startOfWeek");
                LocalDate endOfWeek = dateRange.get("endOfWeek");

                // 生成标题索引：当前时间(年月日时分)+创建者
                String titleIndex = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + "_AI";
                task.setTitleIndex(titleIndex);
                task.setTitle(genParamsResponse);
                task.setCreater(username);
                task.setPeriodStartDate(startOfWeek);
                task.setPeriodEndDate(endOfWeek);
                task.setStatus("todo");
                task.setCreatedTime(LocalDateTime.now());
                task.setUpdateTime(LocalDateTime.now());
                task.setType("暂无分类");
                task.setSubType("暂无子分类");
                task.setLevel("暂无");


                Task savedTask = taskRepository.save(task);
                log.info("任务创建成功, ID: {}, 需求名称: {}, 创建者: {}", savedTask.getId(), genParamsResponse, savedTask.getCreater());
                // 获取当前用户的姓名

                return DepositAIChatResponse.builder()
                       .response("任务创建成功, 任务标题：" + genParamsResponse)
                       .conversationId("测试")
                       .timestamp(LocalDateTime.now())
                       .build();
            }

            log.info("用户的问题类型：闲聊");
            String conversationId = request.getConversationId();
            
            // 如果会话ID为空，创建新会话
            if (StringUtils.isBlank(conversationId)) {
                conversationId = UUID.randomUUID().toString();
            }
            
            // 获取或创建聊天记忆
            ChatMemory memory = getChatMemory(conversationId);
            
            // 将用户消息添加到记忆
            memory.add(new UserMessage(request.getMessage()));
            
            // 获取所有历史消息
            List<ChatMessage> messages = new ArrayList<>();
            messages.add(new SystemMessage(SYSTEM_PROMPT + SYSTEM_PROMPT_WECHAT));
            messages.addAll(memory.messages());

            
            // 获取AI回复
            AiMessage aiMessage = chatModel.generate(messages).content();
            
            // 将AI回复添加到记忆
            memory.add(aiMessage);
            // 清理AI回复中的特殊标记
            String responseText =  aiModelService.cleanModelResponse(aiMessage.text());
            
            // 构建响应对象
            return DepositAIChatResponse.builder()
                    .response(responseText)
                    .conversationId(conversationId)
                    .timestamp(LocalDateTime.now())
                    .build();
        } catch (Exception e) {
            log.error("与AI对话过程中发生错误", e);
            return DepositAIChatResponse.builder()
                    .response("很抱歉，AI助手暂时无法回答您的问题，请稍后再试。错误信息：" + e.getMessage())
                    .conversationId(request.getConversationId())
                    .timestamp(LocalDateTime.now())
                    .build();
        }
    }

    //企业微信AI服务助手对话请求
    @Override
    public String weChat(String request, String username) {
        log.info("系统收到企业微信对话请求: {}, 发送用户是：{}", request, username);
        try {

            //通过提示词判断用户的问题类型
            String prompt = SYSTEM_PROMPT + GET_PROBLEM_TYEP_PROMPT + "\n\n" + "输入:" + request + "\n" + "输出:";
            String response = aiModelService.chat(prompt);
            
            int problemType = Integer.parseInt(response);
            if (problemType == 1) {
                log.info("用户的问题类型：需求相关");
                // 提取出的关键信息
                String genParams = GEN_PARAMS_PROMPT + "\n\n" + "用户输入：" + request + "\n" + "提取结果：";
                String genParamsResponse = aiModelService.chat(genParams);
                log.info("提取出的关键信息：{}", genParamsResponse);
                Task task = new Task();

                // 设置当前周的周一和周日日期
                Map<String, LocalDate> dateRange = DateUtils.getCurrentAndLastWeekDateRange();
                LocalDate startOfWeek = dateRange.get("startOfWeek");
                LocalDate endOfWeek = dateRange.get("endOfWeek");

                // 生成标题索引：当前时间(年月日时分)+创建者
                String titleIndex = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + username;
                task.setTitleIndex(titleIndex);
                task.setTitle(genParamsResponse);
                task.setCreater(username);
                task.setPeriodStartDate(startOfWeek);
                task.setPeriodEndDate(endOfWeek);
                task.setStatus("todo");
                task.setCreatedTime(LocalDateTime.now());
                task.setUpdateTime(LocalDateTime.now());
                task.setType("暂无分类");
                task.setSubType("暂无子分类");
                task.setLevel("暂无");


                Task savedTask = taskRepository.save(task);

                log.info("任务创建成功, ID: {}, 需求名称: {}, 创建者: {}", savedTask.getId(), genParamsResponse, savedTask.getCreater());

                return ("任务创建成功, ID:" + savedTask.getId() + ", 需求名称:"+ genParamsResponse + ", 创建者:" + savedTask.getCreater());
            }

            log.info("用户的问题类型：闲聊");
            String prompt2 = SYSTEM_PROMPT + SYSTEM_PROMPT_WECHAT + "\n\n" + "用户问题:" + request + "\n" + "输出:";
            String result = aiModelService.chat(prompt2);
            return result;
        } catch (Exception e) {
            log.error("与AI对话过程中发生错误", e);
            return ("很抱歉，AI助手暂时无法回答您的问题，请稍后再试。错误信息：" + e.getMessage());
        }
    }

    /**
     * 获取或创建聊天记忆
     *
     * @param conversationId 会话ID
     * @return 聊天记忆对象
     */
    private ChatMemory getChatMemory(String conversationId) {
        return chatMemories.computeIfAbsent(conversationId, id -> {
            // 创建有限窗口大小的聊天记忆，只保留最近的N轮对话
            return MessageWindowChatMemory.builder()
                    .maxMessages(deepSeekConfig.getMaxHistory() * 2) // 乘以2是因为每轮对话包含用户消息和AI消息
                    .build();
        });
    }

} 